/***************************************************************************************
 The copyright in this software is being made available under the BSD License, included
 below. This software may be subject to other third party rights,including patent rights,
 and no such rights are granted under this license.

 Regents of the Tsinghua University, Peking University, Zhejiang University, HKUST
 Tsinghua University, Peking University, Zhejiang University, HKUST 2011

 Copyright (c) 2011, Regents of the Tsinghua University, Peking University, Zhejiang
 University, HKUST. All Rights Reserved.

 Redistribution and use in source and binary forms, with or without modification, are
 permitted provided that the following conditions are met:
   * Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
   * Neither the names of the copyright holders nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 OF SUCH DAMAGE.
***************************************************************************************/

/**************************************************************************************
* File name: image.c
* Function: Decode a Slice
*
*************************************************************************************
*/


#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <sys/timeb.h>
#include <string.h>
#include <assert.h>
#if defined(WIN32) && !defined(__MINGW32__)
#include <IO.H>
#include <STDIO.H>
#endif

#include "contributors.h"
#include "global.h"
#include "header.h"
#include "vlc.h"
#include "memalloc.h"
#include "bbv.h"
#include "macroblock.h"
#include "qcoder.h"

void DecideMvRange();

extern image_t *erc_img;

bbv_buffer_t *pBbv = NULL;

int *last_P_no;
int *last_P_no_frm;
/* 08.16.2007--for user data after pic header */
unsigned char *temp_slice_buf;
int first_slice_length;
int first_slice_startpos;
/* 08.16.2007--for user data after pic header */



//added by xy_110703 begin
/*
*************************************************************************
* Function:
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void decide_next_frame_type( image_t *img )
{

    if( img->type == I_IMG )
    {
        if( img->is_discard_frame == 0 )
            img->next_frame_type = P_IMG;
        else
            img->next_frame_type = I_IMG;
    }
    else
    {
        if ( img->b_num == 0 )
        {
            img->next_frame_type = P_IMG;
            img->b_num = img->succe_b;
        }
        else
        {
            img->next_frame_type = B_IMG;
            img->b_num--;
        }
    }
}

//added by xy_110703 end
/*
*************************************************************************
* Function:decodes one I- or P-frame
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

int decode_one_frame( image_t *img, input_t *inp, snr_t *snr )
{
    int current_header;

    time_t ltime1;
    time_t ltime2;

#if defined(WIN32) && !defined(__MINGW32__)
    struct _timeb tstruct1;
    struct _timeb tstruct2;
#else
    struct timeb tstruct1;
    struct timeb tstruct2;
#endif

    int tmp_time;                 // time used by decoding the last frame
    int i,j;

#if defined(WIN32) && !defined(__MINGW32__)
    _ftime( &tstruct1 );          // start time ms
#else
    ftime( &tstruct1 );           // start time ms
#endif
    time( &ltime1 );              // start time s

    singlefactor = ( float )( ( Bframe_ctr & 0x01 ) ? 0.5 : 2 );

    if ( 0 /*!img->picture_structure*/ )
        singlefactor = 1;

    second_IField = 0;

    if ( input->check_BBV_flag && img->number && pBbv )
    {
        pBbv->frame_code_bits = 0;
    }
    current_header = Header();

    DecideMvRange();

    if ( current_header == EOS )
        return EOS;

    {
        if ( horizontal_size % 16 != 0 )
        {
            img->auto_crop_right = 16 - ( horizontal_size % 16 );
        }
        else
        {
            img->auto_crop_right = 0;
        }

        if ( 0/*!progressive_sequence*/ )
        {
            //if (vertical_size % 32 != 0)
            //{
            //  img->auto_crop_bottom = 32 - (vertical_size % 32);
            //}
            //else
            //{
            //  img->auto_crop_bottom = 0;
            //}
        }
        else
        {
            if ( vertical_size % 16 != 0 )
            {
                img->auto_crop_bottom = 16 - ( vertical_size % 16 );
            }
            else
            {
                img->auto_crop_bottom = 0;
            }
        }

        img->width = ( horizontal_size + img->auto_crop_right );
        img->height = ( vertical_size + img->auto_crop_bottom );
        img->width_cr = ( img->width >> 1 );
        if ( chroma_format == 2 )
            img->height_cr = ( img->height );
        else
            img->height_cr = ( img->height >> 1 );
        img->PicWidthInMbs = img->width / MB_BLOCK_SIZE;
        img->PicHeightInMbs = img->height / MB_BLOCK_SIZE;
        img->PicSizeInMbs = img->PicWidthInMbs * img->PicHeightInMbs;
        img->max_mb_nr = ( img->width * img->height ) / ( MB_BLOCK_SIZE * MB_BLOCK_SIZE );

    }


    img->current_mb_nr = 0;

    init_frame( img, inp );
    if ( 1/*img->picture_structure*/ )
    {
        img->types = img->type;

        if ( img->type != B_IMG )
        {
            pre_img_type = img->type;
            pre_img_types = img->types;
        }

        picture_data( img, inp );
    }

    img->height = ( vertical_size + img->auto_crop_bottom );
    img->height_cr =img->height / ( chroma_format == 2 ? 1 : 2 );
    img->PicWidthInMbs = img->width / MB_BLOCK_SIZE;
    img->PicHeightInMbs = img->height / MB_BLOCK_SIZE;
    img->PicSizeInMbs = img->PicWidthInMbs * img->PicHeightInMbs;

    frame_postprocessing( img );
#if REC_YUV
    if ( img->type == B_IMG )
    {
        if ( p_ref )
            find_snr( snr, img, p_ref );
    }
#endif

#if defined(WIN32) && !defined(__MINGW32__)
    _ftime( &tstruct2 );          // end time ms
#else
    ftime( &tstruct2 );           // end time ms
#endif

    time( &ltime2 );              // end time sec
    tmp_time = ( ltime2 * 1000 + tstruct2.millitm ) - ( ltime1 * 1000 + tstruct1.millitm );
    tot_time = tot_time + tmp_time;

    //added by Zheng Xiaozhen, HiSilicon, 2007.03.21
    if ( img->type != B_IMG )
    {
        pre_tmp_time = tmp_time;
        pre_img_tr = img->tr;
        pre_img_qp = img->qp;
    }


    if ( img->type == B_IMG )
#if REC_YUV
        fprintf( stdout, "%3d(B)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n", FrameNum, img->tr, img->qp, snr->snr_y, snr->snr_u, snr->snr_v, tmp_time, 1/*img->picture_structure*/ ? "FRM" : "FLD" );
#else
        fprintf( stdout, "%3d(B)  %3d %5d %5d\t\t%s\n", FrameNum, img->tr, img->qp, tmp_time, 1/*img->picture_structure*/ ? "FRM" : "FLD" );
#endif

    fflush( stdout );

    if ( img->type == B_IMG )
        report_frame( snr, tmp_time );

    if ( img->type == I_IMG || img->type == P_IMG )
    {
#if DEBLOCK
        CopyAndDeblockFrame( img, imgY_prev_deblock, imgUV_prev_deblock, p_img_y_dec, p_img_uv_dec );
#endif

        for ( i = 0; i < img->height; i++ )
            for ( j = 0; j < img->width; j++ )
            {
                imgY_prev[i][j] = p_img_y_dec[i][j];
            }
        for ( i = 0; i < img->height_cr; i++ )
            for ( j = 0; j < img->width_cr; j++ )
            {
                imgUV_prev[0][i][j] = p_img_uv_dec[0][i][j];
            }
        for ( i = 0; i < img->height_cr; i++ )
            for ( j = 0; j < img->width_cr; j++ )
            {
                imgUV_prev[1][i][j] = p_img_uv_dec[1][i][j];
            }
#ifdef OPT_HP
		if(img->type == P_IMG && img->tag_hp <= 1)
				update_picture_buffers();

		if(img->type == P_IMG && img->tag_hp == 2)
		{
			byte ** tmp_img_y_dec;
			byte ** tmp_img_uv_dec[UV];
			mv_t ** tmp_frm_mv;

			p_img_y_dec=img_y_dec[2];
			p_img_uv_dec[0]=img_uv_dec[0][2];
			p_img_uv_dec[1]=img_uv_dec[1][2];

			tmp_frm_mv=frm_mv[1];
			frm_mv[1]=frm_mv[0];
			frm_mv[0]=tmp_frm_mv;
		}
		else if(img->type == P_IMG && img->tag_hp == 3)
			update_picture_buffers2();
		else if(img->type == I_IMG)
#endif
        update_picture_buffers();
    }
    else                          // B pictures
    {
#if DEBLOCK
        CopyAndDeblockFrame( img, p_img_y_dec_deblock, p_img_uv_dec_deblock, p_img_y_dec, p_img_uv_dec );
#endif

        write_frame( img, p_out );  // write image to output YUV file
    }

    if ( input->check_BBV_flag )
    {
        update_bbv( pBbv, pBbv->frame_code_bits );
    }


    if ( img->type == I_IMG || img->type == P_IMG ) // I or P pictures
        img->number++;
    else
        Bframe_ctr++;               // B pictures

    decide_next_frame_type( img ); //added by xy_110703


    return ( SOP );
}



/*
*************************************************************************
* Function:
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void report_frame( snr_t *snr, int tmp_time )
{
    FILE *file;
    file = fopen( "stat.dat", "at" );
#if REC_YUV
    if ( img->type == I_IMG )
        fprintf( file, "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n", FrameNum, pre_img_tr, pre_img_qp, snr->snr_y, snr->snr_u, snr->snr_v, pre_tmp_time, 1 /*img->picture_structure*/ ? "FRM" : "FLD" ); //20080721
    else if ( img->type == P_IMG )
        fprintf( file, "%3d(P)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n", FrameNum, pre_img_tr, pre_img_qp, snr->snr_y, snr->snr_u, snr->snr_v, pre_tmp_time, 1 /*img->picture_structure*/ ? "FRM" : "FLD" );
    else
        fprintf( file, "%3d(B)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n", FrameNum, img->tr, img->qp, snr->snr_y, snr->snr_u, snr->snr_v, tmp_time, 1 /*img->picture_structure*/ ? "FRM" : "FLD" );
#else
    if ( img->type == I_IMG )
        fprintf( file, "%3d(I)  %3d %5d %5d\t\t%s\n", FrameNum, pre_img_tr, pre_img_qp, pre_tmp_time, 1 /*img->picture_structure*/ ? "FRM" : "FLD" ); //20080721
    else if ( img->type == P_IMG )
        fprintf( file, "%3d(P)  %3d %5d %5d\t\t%s\n", FrameNum, pre_img_tr, pre_img_qp, pre_tmp_time, 1 /*img->picture_structure*/ ? "FRM" : "FLD" );
    else
        fprintf( file, "%3d(B)  %3d %5d %5d\t\t%s\n", FrameNum, img->tr, img->qp, tmp_time, 1 /*img->picture_structure*/ ? "FRM" : "FLD" );
#endif
    FrameNum++;
    fclose( file );
}

/*
*************************************************************************
* Function:Find PSNR for all three components.Compare decoded frame with
the original sequence. Read inp->jumpd frames to reflect frame skipping.
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
#if REC_YUV
#if defined(WIN32) && !defined(__MINGW32__)
void find_snr( snr_t *snr,
               image_t *img,
               int p_ref )
#else
void find_snr( snr_t *snr,
               image_t *img,
               FILE * p_ref )
#endif
{
    int i, j;
    int diff_y, diff_u, diff_v;
    int uv;
    int uvformat = chroma_format == 2 ? 2 : 4;
#if defined(WIN32) && !defined(__MINGW32__)
    __int64 status;
#else
    int status;
#endif

    int img_width = ( img->width - img->auto_crop_right );
    int img_height = ( img->height - img->auto_crop_bottom );
    int img_width_cr = ( img_width / 2 );
    int img_height_cr = ( img_height / ( chroma_format == 2 ? 1 : 2 ) );
#if defined(WIN32) && !defined(__MINGW32__)
    const unsigned int bytes_y = img_width * img_height;
    const unsigned int bytes_uv = img_width_cr * img_height_cr;
    const __int64 framesize_in_bytes = ( __int64 ) ( bytes_y + 2 * bytes_uv );
#else
    const unsigned int bytes_y = img_width * img_height;
    const unsigned int bytes_uv = img_width_cr * img_height_cr;
    const int framesize_in_bytes = bytes_y + 2 * bytes_uv;
#endif
    unsigned char *buf;
    int offset_units;

    if ( !input->yuv_structure )
        buf = malloc( bytes_y );
    else
        buf = malloc( bytes_y + 2 * bytes_uv );
    if ( NULL == buf )
    {
        no_mem_exit( "find_snr: buf" );
    }
    snr->snr_y = 0.0;
    snr->snr_u = 0.0;
    snr->snr_v = 0.0;

#if defined(WIN32) && !defined(__MINGW32__)
#else
    rewind( p_ref );
#endif

    if ( RefPicExist )
    {
#if defined(WIN32) && !defined(__MINGW32__)
        status = lseek( p_ref, framesize_in_bytes * FrameNum, SEEK_SET );
#else
        status = fseek( p_ref, framesize_in_bytes * FrameNum, 0 );
#endif

#if defined(WIN32) && !defined(__MINGW32__)
        if ( status == -1 )
#else
        if ( status != 0 )
#endif
        {
            snprintf( errortext, ET_SIZE, "Error in seeking img->tr: %d", img->tr );
            RefPicExist = 0;
        }
    }
#if defined(WIN32) && !defined(__MINGW32__)
    if ( !input->yuv_structure )
        _read( p_ref, buf, bytes_y );
    else
        _read( p_ref, buf, bytes_y + 2 * bytes_uv );
    if ( !input->yuv_structure )  //YUV
    {
        for ( j = 0; j < img_height; j++ )
            memcpy( &imgY_ref[j][0], buf + j * img_width, img_width );
    }
    else                          //U0Y0 V1Y1
    {
        for ( j = 0; j < img_height; j++ )
            for ( i = 0; i < img_width; i++ )
            {
                offset_units = j * img_width + i;
                imgY_ref[j][i] = buf[2 * offset_units + 1];
                if ( offset_units % 2 == 0 )    //U component
                    imgUV_ref[0][j][i / 2] = buf[2 * offset_units];
                else                    //V component
                    imgUV_ref[1][j][i / 2] = buf[2 * offset_units];
            }
    }
#else
    if ( !input->yuv_structure )
    {
        for ( j = 0; j < img_height; j++ )
            for ( i = 0; i < img_width; i++ )
                imgY_ref[j][i] = fgetc( p_ref );
    }
    else
    {
        for ( j = 0; j < img_height; j++ )
            for ( i = 0; i < img_width; i++ )
            {
                offset_units = j * img_width + i;
                if ( offset_units % 2 == 0 )    //U component
                    imgUV_ref[0][j][i / 2] = fgetc( p_ref );
                else                    //V component
                    imgUV_ref[1][j][i / 2] = fgetc( p_ref );

                imgY_ref[j][i] = fgetc( p_ref );
            }
    }
#endif

    for ( uv = 0; uv < 2; uv++ )
    {
        if ( !input->yuv_structure )
        {
#if defined(WIN32) && !defined(__MINGW32__)
            _read( p_ref, buf, img_height_cr * img_width_cr );
            for ( j = 0; j < img_height_cr; j++ )
                memcpy( &imgUV_ref[uv][j][0], buf + j * img_width_cr, img_width_cr );
#else
            for ( j = 0; j < img_height_cr; j++ )
                for ( i = 0; i < img_width_cr; i++ )
                    imgUV_ref[uv][j][i] = fgetc( p_ref );
#endif
        }
    }

    img->quad[0] = 0;
    diff_y = 0;
    for ( j = 0; j < img_height; ++j )
    {
        for ( i = 0; i < img_width; ++i )
        {
            if ( img->type == B_IMG && !eos )
                diff_y += img->quad[abs( p_img_y_dec[j][i] - imgY_ref[j][i] )];
            else
                diff_y += img->quad[abs( imgY_prev[j][i] - imgY_ref[j][i] )];

            if ( img->type == B_IMG && !eos )
            {
                if ( p_img_y_dec[j][i] != imgY_ref[j][i] )
                {
                    int mb_nr;
                    mb_nr = ( j / 16 ) * ( img->width / 16 ) + i / 16;
                }
            }
            else
            {
                if ( /*imgY */ imgY_ref[j][i] != imgY_prev[j][i] )
                {
                    int mb_nr;
                    mb_nr = ( j / 16 ) * ( img->width / 16 ) + i / 16;
                }
            }
        }
    }
    diff_u = 0;
    diff_v = 0;

    for ( j = 0; j < img_height_cr; ++j )
    {
        for ( i = 0; i < img_width_cr; ++i )
        {
            if ( img->type == B_IMG && !eos )
            {
                diff_u += img->quad[abs( imgUV_ref[0][j][i] - p_img_uv_dec[0][j][i] )];
                diff_v += img->quad[abs( imgUV_ref[1][j][i] - p_img_uv_dec[1][j][i] )];
            }
            else
            {
                diff_u += img->quad[abs( imgUV_ref[0][j][i] - imgUV_prev[0][j][i] )];
                diff_v += img->quad[abs( imgUV_ref[1][j][i] - imgUV_prev[1][j][i] )];
            }

            if ( img->type == B_IMG && !eos )
            {
                if ( imgUV_ref[0][j][i] != p_img_uv_dec[0][j][i] )
                {
                    int mb_nr;
                    mb_nr = ( j / 16 ) * ( img->width / 16 ) + i / 8;
                }
            }
            else
            {
                if ( imgUV_prev[0][j][i] != p_img_uv_dec[0][j][i] )
                {
                    int mb_nr;
                    mb_nr = ( j / 16 ) * ( img->width / 16 ) + i / 8;
                }
            }

        }
    }

    // Collecting SNR statistics
    if ( diff_y != 0 )
        snr->snr_y = ( float )( 10 * log10( 65025 * ( float )( img_width  ) * ( img_height ) / ( float )diff_y ) );
    if ( diff_u != 0 )
        snr->snr_u = ( float )( 10 * log10( 65025 * ( float )( img_width  ) * ( img_height ) / ( float )( uvformat * diff_u ) ) );
    if ( diff_v != 0 )
        snr->snr_v = ( float )( 10 * log10( 65025 * ( float )( img_width  ) * ( img_height ) / ( float )(  uvformat * diff_v ) ) );

    if ( img->number ==1 )
    {
        snr->snr_y1 = ( float )( 10 * log10( 65025 * ( float )( img_width  ) * ( img_height ) / ( float )diff_y ) );
        snr->snr_u1 = ( float )( 10 * log10( 65025 * ( float )( img_width ) * ( img_height ) / ( float )( uvformat * diff_u ) ) );
        snr->snr_v1 = ( float )( 10 * log10( 65025 * ( float )( img_width ) * ( img_height ) / ( float )( uvformat * diff_v ) ) );
        snr->snr_ya = snr->snr_y1;
        snr->snr_ua = snr->snr_u1;
        snr->snr_va = snr->snr_v1;

        if ( diff_y == 0 )
            snr->snr_ya = 0;
        if ( diff_u == 0 )
            snr->snr_ua = 0;
        if ( diff_v == 0 )
            snr->snr_va = 0;
    }
    else
    {
        snr->snr_ya = ( float )( snr->snr_ya * ( img->number + Bframe_ctr - 1 ) + snr->snr_y ) / ( img->number + Bframe_ctr ); // average snr chroma for all frames 20080721
        snr->snr_ua = ( float )( snr->snr_ua * ( img->number + Bframe_ctr - 1 ) + snr->snr_u ) / ( img->number + Bframe_ctr ); // average snr luma for all frames 20080721
        snr->snr_va = ( float )( snr->snr_va * ( img->number + Bframe_ctr - 1 ) + snr->snr_v ) / ( img->number + Bframe_ctr ); // average snr luma for all frames 20080721
    }

    free( buf );
}
#endif

/*
*************************************************************************
* Function:Interpolation of 1/4 subpixel
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
#if QUARTER_wangIF
void get_block( int ref_frame, int x_pos, int y_pos, image_t *img, int block[8][8] )
{

	int dx, dy;
	int x, y;
	int i, j;
	int maxold_x, maxold_y;
	int result;
	int tmp_res[26][26];


	static const int COEF_HALF_8tap[8] = {
		-1, 4, -11, 40, 40, -11, 4, -1
	};
	static const int COEF_QUART1_8tap[8] = {
		-1, 4, -10, 57, 18, -6, 3, -1
	};
	static const int COEF_QUART3_8tap[8] = {
		-1, 3, -6, 18, 57, -10, 4, -1
	};

	static const int COEF_HALF_6tap[6] = {
		2, -9, 39, 39, -9, 2
	};
	static const int COEF_QUART1_6tap[6] = {
		2, -9, 57, 17, -4, 1
	};
	static const int COEF_QUART3_6tap[6] = {
		1, -4, 17, 57, -9, 2
	};

	//    A  a  b  c  B
	//    d  e  f  g
	//    h  i  j  k
	//    n  p  q  r
	//    C           D

	//  in encoder, static void up_sampling()
	//    IA A1 A  A2 IB
	//    B1 C1 D3 C2
	//    B  D1 C  D2
	//    B2 C3 D4 C4
	//    IC          ID

#if QUARTER_PIXEL
	dx = x_pos & 3;
	dy = y_pos & 3;
	x_pos = ( x_pos - dx ) / 4;
	y_pos = ( y_pos - dy ) / 4;
#else
	dx = x_pos & 1;
	dy = y_pos & 1;
	x_pos = ( x_pos - dx ) / 2;
	y_pos = ( y_pos - dy ) / 2;
#endif

	maxold_x = img->width - 1;
	maxold_y = img->height - 1;

	if ( dx == 0 && dy == 0 )
	{
		//fullpel position: A
		for ( j = 0; j < B8_SIZE; j++ )
			for ( i = 0; i < B8_SIZE; i++ )
				block[i][j] = img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i ) )];
	}
	else
	{
		/* other positions */

		// 1D interpolation, 6 points 


#if QUARTER_PIXEL
		if ( ( dx == 2 ) && ( dy == 0 ) )
#else
		if ( ( dx == 1 ) && ( dy == 0 ) )
#endif
		{
			//horizontal 1/2 position: b
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{
					for ( result = 0, x = -3; x < 5; x++ )//-3~4
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF_8tap[x + 3];
					block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
		}

#if QUARTER_PIXEL
		else if ( ( dy == 2 ) && ( dx == 0 ) ) 
#else
		else if ( ( dy == 1 ) && ( dx == 0 ) )
#endif
		{
			//vertical 1/2 position: h
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{
					for ( result = 0, y = -3; y < 5; y++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j + y ) )][RFM_MAX( 0, min( maxold_x, x_pos + i ) )] * COEF_HALF_8tap[y + 3];
					block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
		}

#if QUARTER_PIXEL
		else if ( ( dx == 2 ) && ( dy == 2 ) ) //dw 20110808
#else
		else if ( ( dx == 1 ) && ( dy == 1 ) )
#endif
		{
			//horizontal 1/2 and vertical 1/2 position: j
			for ( j = -2; j < B8_SIZE + 3; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF_8tap[x + 3];


					
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_HALF_6tap[y + 2];


					
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));

				}
			}

		}


#if QUARTER_PIXEL
		else if ( ( dx == 1 ) && ( dy == 0 ) )
		{
			//horizontal 1/4 position: a
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{
					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART1_8tap[x + 3];
					block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) ); 

				}
			}

		}

		else if ( ( dx == 3 ) && ( dy == 0 ) )
		{
			//horizontal 3/4 position: c
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{
					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART3_8tap[x + 3];
					block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) ); 
				}
			}
		}

		else if ( ( dx == 0 ) && ( dy == 1 ) )
		{
			//vertical 1/4 position: d
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{
					for ( result = 0, y = -3; y < 5; y++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j + y ) )][RFM_MAX( 0, min( maxold_x, x_pos + i ) )] * COEF_QUART1_8tap[y + 3];
					block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
		}



		else if ( ( dx == 0 ) && ( dy == 3 ) )
		{
			//vertical 3/4 position: n
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{
					for ( result = 0, y = -3; y < 5; y++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j + y ) )][RFM_MAX( 0, min( maxold_x, x_pos + i ) )] * COEF_QUART3_8tap[y + 3];
					block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
		}

		//remaining 9 points
		//e,i,p
		else if ( ( dx == 1 ) && ( dy == 1 ) )
		{
			//horizontal 1/4 and vertical 1/4 position: e
			for ( j = -2; j < B8_SIZE + 3; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART1_8tap[x + 3];

					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
					

				}
			}
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_QUART1_6tap[y + 2];

					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
					
				}
			}

		}

		else if ( ( dx == 1 ) && ( dy == 2 ) )
		{
			//horizontal 1/4 and vertical 1/2 position: i
			for ( j = -2; j < B8_SIZE + 3; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART1_8tap[x + 3];


					
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_HALF_6tap[y + 2];


					
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}

		}

		else if ( ( dx == 1 ) && ( dy == 3 ) )
		{
			////horizontal 1/4 and vertical 3/4 position: p
			for ( j = -2; j < B8_SIZE + 3; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART1_8tap[x + 3];


					
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_QUART3_6tap[y + 2];


					
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}

		}

		//f,j,q
		else if ( ( dx == 2 ) && ( dy == 1 ) )
		{
			//horizontal 1/2 and vertical 1/4 position: f
			for ( j = -2; j < B8_SIZE + 3; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF_8tap[x + 3];


					
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_QUART1_6tap[y + 2];


					
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}

		}


		else if ( ( dx == 2 ) && ( dy == 3 ) )
		{
			//horizontal 1/2 and vertical 3/4 position: q
			for ( j = -2; j < B8_SIZE + 3; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF_8tap[x + 3];


					
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_QUART3_6tap[y + 2];


					
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}

		}

		//g,k,r
		else if ( ( dx == 3 ) && ( dy == 1 ) )
		{
			//horizontal 3/4 and vertical 1/4 position: g
			for ( j = -2; j < B8_SIZE + 3; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART3_8tap[x + 3];


					
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_QUART1_6tap[y + 2];


					
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}

		}



		else if ( ( dx == 3 ) && ( dy == 2 ) )
		{
			//horizontal 3/4 and vertical 1/2 position: k
			for ( j = -2; j < B8_SIZE + 3; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART3_8tap[x + 3];


					
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );

				}
			}
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_HALF_6tap[y + 2];


					
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}

		}

		else if ( ( dx == 3 ) && ( dy == 3 ) )
		{
			//horizontal 3/4 and vertical 3/4 position: r
			for ( j = -2; j < B8_SIZE + 3; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART3_8tap[x + 3];


					
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B8_SIZE; j++ )
			{
				for ( i = 0; i < B8_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_QUART3_6tap[y + 2];


					
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}

		}

#endif

	}
}
#else
void get_block( int ref_frame, int x_pos, int y_pos, image_t *img, int block[8][8] )
{

    int dx, dy;
    int x, y;
    int i, j;
    int maxold_x, maxold_y;
    int result;
    int tmp_res[26][26];
    static const int COEF_HALF[4] =
    {
        //-1, 5, 5, -1
        0, 4, 4, 0
    };
#if QUARTER_PIXEL
    static const int COEF_QUART_LT[4] =     //dw 20110808
    {
        0, 3, 1, 0
    };
    static const int COEF_QUART_RB[4] =     //dw 20110808
    {
        0, 1, 3, 0
    };

    //    IA A1 A  A2 IB     //dw 20110808
    //    B1 C1 D3 C4
    //    B  D1 C  D2
    //    B2 C2 D4 C3
    //    IC          ID
#else
    //static const int COEF_QUART[4] = {
    //  1, 7, 7, 1
    //};

    //    A  a  1  b  B
    //    c  d  e  f
    //    2  h  3  i
    //    j  k  l  m
    //    C           D
#endif

#if QUARTER_PIXEL
    dx = x_pos & 3;  //dw 20110808
    dy = y_pos & 3;  //dw 20110808
    x_pos = ( x_pos - dx ) / 4; //dw 20110808
    y_pos = ( y_pos - dy ) / 4; //dw 20110808
#else
    dx = x_pos & 1;
    dy = y_pos & 1;
    x_pos = ( x_pos - dx ) / 2;
    y_pos = ( y_pos - dy ) / 2;
#endif
    maxold_x = img->width - 1;
    maxold_y = img->height - 1;

    if ( dx == 0 && dy == 0 )
    {
        //fullpel position: A
        for ( j = 0; j < B8_SIZE; j++ )
            for ( i = 0; i < B8_SIZE; i++ )
                block[i][j] = img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i ) )];
    }
    else
    {
        /* other positions */
#if QUARTER_PIXEL
        if ( ( dx == 2 ) && ( dy == 0 ) ) //dw 20110808
#else
        if ( ( dx == 1 ) && ( dy == 0 ) )
#endif
        {
            //horizonal 1/2 position: 1
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {
                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF[x + 1];
                    block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
        }

#if QUARTER_PIXEL
        else if ( ( dy == 2 ) && ( dx == 0 ) ) //dw 20110808
#else
        else if ( ( dy == 1 ) && ( dx == 0 ) )
#endif
        {
            //vertical 1/2 position: 2
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {
                    for ( result = 0, y = -1; y < 3; y++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j + y ) )][RFM_MAX( 0, min( maxold_x, x_pos + i ) )] * COEF_HALF[y + 1];
                    block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
        }

#if QUARTER_PIXEL
        else if ( ( dx == 2 ) && ( dy == 2 ) ) //dw 20110808
#else
        else if ( ( dx == 1 ) && ( dy == 1 ) )
#endif
        {
            //horizonal and vertical 1/2 position: 3
            for ( j = -1; j < B8_SIZE + 2; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {
                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF[x + 1];
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {
                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_HALF[y + 1];
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
        }
#if QUARTER_PIXEL
        // quarter-pixel  //dw 20110808
        else if ( ( dx == 1 ) && ( dy == 0 ) )
        {
            //position: A1
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {
                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_LT[x + 1];
                    block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) ); // ???? +4
                }
            }
        }

        else if ( ( dx == 3 ) && ( dy == 0 ) )
        {
            //position: A2
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {
                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_RB[x + 1];
                    block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) ); // ???? +4
                }
            }
        }

        else if ( ( dx == 0 ) && ( dy == 1 ) )
        {
            //position: B1
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {
                    for ( result = 0, y = -1; y < 3; y++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j + y ) )][RFM_MAX( 0, min( maxold_x, x_pos + i ) )] * COEF_QUART_LT[y + 1];
                    block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) ); // ???? +4
                }
            }
        }

        else if ( ( dx == 0 ) && ( dy == 3 ) )
        {
            //position: B2
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {
                    for ( result = 0, y = -1; y < 3; y++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j + y ) )][RFM_MAX( 0, min( maxold_x, x_pos + i ) )] * COEF_QUART_RB[y + 1];
                    block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) ); // ???? +4
                }
            }
        }

        else if ( ( dx == 1 ) && ( dy == 1 ) )
        {
            //position: C1
            for ( j = -1; j < B8_SIZE + 2; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_LT[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_QUART_LT[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
        }

        else if ( ( dx == 1 ) && ( dy == 3 ) )
        {
            //position: C2
            for ( j = -1; j < B8_SIZE + 2; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_LT[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_QUART_RB[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
        }

        else if ( ( dx == 3 ) && ( dy == 3 ) )
        {
            //position: C3
            for ( j = -1; j < B8_SIZE + 2; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_RB[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_QUART_RB[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
        }

        else if ( ( dx == 3 ) && ( dy == 1 ) )
        {
            //position: C4
            for ( j = -1; j < B8_SIZE + 2; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_RB[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_QUART_LT[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
        }

        else if ( ( dx == 1 ) && ( dy == 2 ) )
        {
            //position: D1
            for ( j = -1; j < B8_SIZE + 2; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_LT[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_HALF[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
        }

        else if ( ( dx == 3 ) && ( dy == 2 ) )
        {
            //position: D2
            for ( j = -1; j < B8_SIZE + 2; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_RB[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_HALF[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
        }

        else if ( ( dx == 2 ) && ( dy == 1 ) )
        {
            //position: D3
            for ( j = -1; j < B8_SIZE + 2; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_QUART_LT[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
        }

        else if ( ( dx == 2 ) && ( dy == 3 ) )
        {
            //position: D4
            for ( j = -1; j < B8_SIZE + 2; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
            for ( j = 0; j < B8_SIZE; j++ )
            {
                for ( i = 0; i < B8_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_QUART_RB[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
        }
#endif
    }
}
#endif
/*
*************************************************************************
* Function:Interpolation of 1/4 subpixel
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
#if QUARTER_wangIF
void get_block_4x4( int ref_frame, int x_pos, int y_pos, image_t *img, int block[4][4] )
{

	int dx, dy;
	int x, y;
	int i, j;
	int maxold_x, maxold_y;
	int result;
	int tmp_res[26][26];


	static const int COEF_HALF_8tap[8] = {
		-1, 4, -11, 40, 40, -11, 4, -1
	};
	static const int COEF_QUART1_8tap[8] = {
		-1, 4, -10, 57, 18, -6, 3, -1
	};
	static const int COEF_QUART3_8tap[8] = {
		-1, 3, -6, 18, 57, -10, 4, -1
	};

	static const int COEF_HALF_6tap[6] = {
		2, -9, 39, 39, -9, 2
	};
	static const int COEF_QUART1_6tap[6] = {
		2, -9, 57, 17, -4, 1
	};
	static const int COEF_QUART3_6tap[6] = {
		1, -4, 17, 57, -9, 2
	};


	//    A  a  b  c  B
	//    d  e  f  g
	//    h  i  j  k
	//    n  p  q  r
	//    C           D

	//  in encoder, static void up_sampling()
	//    IA A1 A  A2 IB
	//    B1 C1 D3 C2
	//    B  D1 C  D2
	//    B2 C3 D4 C4
	//    IC          ID

#if QUARTER_PIXEL
	dx = x_pos & 3;
	dy = y_pos & 3;
	x_pos = ( x_pos - dx ) / 4;
	y_pos = ( y_pos - dy ) / 4;
#else
	dx = x_pos & 1;
	dy = y_pos & 1;
	x_pos = ( x_pos - dx ) / 2;
	y_pos = ( y_pos - dy ) / 2;
#endif

	maxold_x = img->width - 1;
	maxold_y = img->height - 1;

	if ( dx == 0 && dy == 0 )
	{
		//fullpel position: A
		for ( j = 0; j < B4_SIZE; j++ )
			for ( i = 0; i < B4_SIZE; i++ )
				block[i][j] = img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i ) )];
	}
	else
	{
		/* other positions */

		// 1D interpolation, 6 points 


#if QUARTER_PIXEL
		if ( ( dx == 2 ) && ( dy == 0 ) )
#else
		if ( ( dx == 1 ) && ( dy == 0 ) )
#endif
		{
			//horizontal 1/2 position: b
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{
					for ( result = 0, x = -3; x < 5; x++ )//-3~4
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF_8tap[x + 3];
					block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
		}

#if QUARTER_PIXEL
		else if ( ( dy == 2 ) && ( dx == 0 ) ) 
#else
		else if ( ( dy == 1 ) && ( dx == 0 ) )
#endif
		{
			//vertical 1/2 position: h
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{
					for ( result = 0, y = -3; y < 5; y++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j + y ) )][RFM_MAX( 0, min( maxold_x, x_pos + i ) )] * COEF_HALF_8tap[y + 3];
					block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
		}

#if QUARTER_PIXEL
		else if ( ( dx == 2 ) && ( dy == 2 ) ) //dw 20110808
#else
		else if ( ( dx == 1 ) && ( dy == 1 ) )
#endif
		{
			//horizontal 1/2 and vertical 1/2 position: j
			for ( j = -2; j < B4_SIZE + 3; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF_8tap[x + 3];


					//tmp_res[j+2][i]= result;
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_HALF_6tap[y + 2];


					//block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2048 ) / 4096 ) );
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}
		}


#if QUARTER_PIXEL
		else if ( ( dx == 1 ) && ( dy == 0 ) )
		{
			//horizontal 1/4 position: a
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{
					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART1_8tap[x + 3];
					block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) ); 
				}
			}
		}

		else if ( ( dx == 3 ) && ( dy == 0 ) )
		{
			//horizontal 3/4 position: c
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{
					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART3_8tap[x + 3];
					block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) ); 
				}
			}
		}

		else if ( ( dx == 0 ) && ( dy == 1 ) )
		{
			//vertical 1/4 position: d
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{
					for ( result = 0, y = -3; y < 5; y++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j + y ) )][RFM_MAX( 0, min( maxold_x, x_pos + i ) )] * COEF_QUART1_8tap[y + 3];
					block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
		}



		else if ( ( dx == 0 ) && ( dy == 3 ) )
		{
			//vertical 3/4 position: n
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{
					for ( result = 0, y = -3; y < 5; y++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j + y ) )][RFM_MAX( 0, min( maxold_x, x_pos + i ) )] * COEF_QUART3_8tap[y + 3];
					block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
		}

		//remaining 9 points
		//e,i,p
		else if ( ( dx == 1 ) && ( dy == 1 ) )
		{
			//horizontal 1/4 and vertical 1/4 position: e
			for ( j = -2; j < B4_SIZE + 3; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART1_8tap[x + 3];

					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
					//tmp_res[j+2][i]=result;
				}
			}
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_QUART1_6tap[y + 2];

					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
					//block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2048 ) / 4096 ) );
				}
			}
		}

		else if ( ( dx == 1 ) && ( dy == 2 ) )
		{
			//horizontal 1/4 and vertical 1/2 position: i
			for ( j = -2; j < B4_SIZE + 3; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART1_8tap[x + 3];


					//tmp_res[j+2][i]=result;
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_HALF_6tap[y + 2];


					//block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2048 ) / 4096 ) );
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}
		}

		else if ( ( dx == 1 ) && ( dy == 3 ) )
		{
			////horizontal 1/4 and vertical 3/4 position: p
			for ( j = -2; j < B4_SIZE + 3; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART1_8tap[x + 3];


					//tmp_res[j+2][i]=result;
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_QUART3_6tap[y + 2];


					//block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2048 ) / 4096 ) );
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}
		}

		//f,j,q
		else if ( ( dx == 2 ) && ( dy == 1 ) )
		{
			//horizontal 1/2 and vertical 1/4 position: f
			for ( j = -2; j < B4_SIZE + 3; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF_8tap[x + 3];


					//tmp_res[j+2][i]= result;
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_QUART1_6tap[y + 2];


					//block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2048 ) / 4096 ) );
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}
		}


		else if ( ( dx == 2 ) && ( dy == 3 ) )
		{
			//horizontal 1/2 and vertical 3/4 position: q
			for ( j = -2; j < B4_SIZE + 3; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF_8tap[x + 3];


					//tmp_res[j+2][i]= result;
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_QUART3_6tap[y + 2];


					//block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2048 ) / 4096 ) );
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}
		}

		//g,k,r
		else if ( ( dx == 3 ) && ( dy == 1 ) )
		{
			//horizontal 3/4 and vertical 1/4 position: g
			for ( j = -2; j < B4_SIZE + 3; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART3_8tap[x + 3];


					//tmp_res[j+2][i]=result;
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_QUART1_6tap[y + 2];


					//block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2048 ) / 4096 ) );
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}
		}



		else if ( ( dx == 3 ) && ( dy == 2 ) )
		{
			//horizontal 3/4 and vertical 1/2 position: k
			for ( j = -2; j < B4_SIZE + 3; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART3_8tap[x + 3];


					//tmp_res[j+2][i]= result;
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );

				}
			}
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_HALF_6tap[y + 2];


					//block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2048 ) / 4096 ) );
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}
		}

		else if ( ( dx == 3 ) && ( dy == 3 ) )
		{
			//horizontal 3/4 and vertical 3/4 position: r
			for ( j = -2; j < B4_SIZE + 3; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, x = -3; x < 5; x++ )
						result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART3_8tap[x + 3];


					//tmp_res[j+2][i]=result;
					tmp_res[j+2][i]= RFM_MAX( 0, RFM_MIN( 255, ( result+32 ) / 64 ) );
				}
			}
			for ( j = 0; j < B4_SIZE; j++ )
			{
				for ( i = 0; i < B4_SIZE; i++ )
				{

					for ( result = 0, y = -2; y < 4; y++ )
						result += tmp_res[j + y + 2][i] * COEF_QUART3_6tap[y + 2];


					//block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2048 ) / 4096 ) );
					block[i][j] = RFM_MAX(0, RFM_MIN(255, (result+32) / 64));
				}
			}
		}

#endif

	}
}
#else
void get_block_4x4( int ref_frame, int x_pos, int y_pos, image_t *img, int block[4][4] )
{

    int dx, dy;
    int x, y;
    int i, j;
    int maxold_x, maxold_y;
    int result;
    int tmp_res[26][26];
    static const int COEF_HALF[4] =
    {
        //-1, 5, 5, -1
        0, 4, 4, 0
    };
#if QUARTER_PIXEL
    static const int COEF_QUART_LT[4] =     //dw 20110808
    {
        0, 3, 1, 0
    };
    static const int COEF_QUART_RB[4] =     //dw 20110808
    {
        0, 1, 3, 0
    };

    //    IA A1 A  A2 IB     //dw 20110808
    //    B1 C1 D3 C4
    //    B  D1 C  D2
    //    B2 C2 D4 C3
    //    IC          ID
#else
    //static const int COEF_QUART[4] = {
    //  1, 7, 7, 1
    //};

    //    A  a  1  b  B
    //    c  d  e  f
    //    2  h  3  i
    //    j  k  l  m
    //    C           D
#endif

#if QUARTER_PIXEL
    dx = x_pos & 3; //dw 20110808
    dy = y_pos & 3; //dw 20110808
    x_pos = ( x_pos - dx ) / 4; //dw 20110808
    y_pos = ( y_pos - dy ) / 4; //dw 20110808
#else
    dx = x_pos & 1;
    dy = y_pos & 1;
    x_pos = ( x_pos - dx ) / 2;
    y_pos = ( y_pos - dy ) / 2;
#endif
    maxold_x = img->width - 1;
    maxold_y = img->height - 1;

    if ( dx == 0 && dy == 0 )
    {
        //fullpel position: A
        for ( j = 0; j < B4_SIZE; j++ )
            for ( i = 0; i < B4_SIZE; i++ )
                block[i][j] = img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i ) )];
    }
    else
    {
        /* other positions */
#if QUARTER_PIXEL
        if ( ( dx == 2 ) && ( dy == 0 ) ) //dw 20110808
#else
        if ( ( dx == 1 ) && ( dy == 0 ) )
#endif
        {
            //horizonal 1/2 position: 1
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {
                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF[x + 1];
                    block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) ); // ???? +4
                }
            }
        }

#if QUARTER_PIXEL
        else if ( ( dy == 2 ) && ( dx == 0 ) ) //dw 20110808
#else
        else if ( ( dy == 1 ) && ( dx == 0 ) )
#endif
        {
            //vertical 1/2 position: 2
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {
                    for ( result = 0, y = -1; y < 3; y++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j + y ) )][RFM_MAX( 0, min( maxold_x, x_pos + i ) )] * COEF_HALF[y + 1];
                    block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) ); // ???? +4
                }
            }
        }

#if QUARTER_PIXEL
        else if ( ( dx == 2 ) && ( dy == 2 ) ) //dw 20110808
#else
        else if ( ( dx == 1 ) && ( dy == 1 ) )
#endif
        {
            //horizonal and vertical 1/2 position: 3
            for ( j = -1; j < B4_SIZE + 2; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF[x + 1];

                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_HALF[y + 1];

                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
        }
#if QUARTER_PIXEL
        // quarter-pixel  //dw 20110808
        else if ( ( dx == 1 ) && ( dy == 0 ) )
        {
            //position: A1
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {
                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_LT[x + 1];
                    block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) ); // ???? +4
                }
            }
        }

        else if ( ( dx == 3 ) && ( dy == 0 ) )
        {
            //position: A2
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {
                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_RB[x + 1];
                    block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) ); // ???? +4
                }
            }
        }

        else if ( ( dx == 0 ) && ( dy == 1 ) )
        {
            //position: B1
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {
                    for ( result = 0, y = -1; y < 3; y++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j + y ) )][RFM_MAX( 0, min( maxold_x, x_pos + i ) )] * COEF_QUART_LT[y + 1];
                    block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) ); // ???? +4
                }
            }
        }

        else if ( ( dx == 0 ) && ( dy == 3 ) )
        {
            //position: B2
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {
                    for ( result = 0, y = -1; y < 3; y++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j + y ) )][RFM_MAX( 0, min( maxold_x, x_pos + i ) )] * COEF_QUART_RB[y + 1];
                    block[i][j] = RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) ); // ???? +4
                }
            }
        }

        else if ( ( dx == 1 ) && ( dy == 1 ) )
        {
            //position: C1
            for ( j = -1; j < B4_SIZE + 2; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_LT[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_QUART_LT[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
        }

        else if ( ( dx == 1 ) && ( dy == 3 ) )
        {
            //position: C2
            for ( j = -1; j < B4_SIZE + 2; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_LT[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_QUART_RB[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
        }

        else if ( ( dx == 3 ) && ( dy == 3 ) )
        {
            //position: C3
            for ( j = -1; j < B4_SIZE + 2; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_RB[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_QUART_RB[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
        }

        else if ( ( dx == 3 ) && ( dy == 1 ) )
        {
            //position: C4
            for ( j = -1; j < B4_SIZE + 2; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_RB[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_QUART_LT[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
        }

        else if ( ( dx == 1 ) && ( dy == 2 ) )
        {
            //position: D1
            for ( j = -1; j < B4_SIZE + 2; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_LT[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_HALF[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
        }

        else if ( ( dx == 3 ) && ( dy == 2 ) )
        {
            //position: D2
            for ( j = -1; j < B4_SIZE + 2; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_QUART_RB[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_HALF[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
        }

        else if ( ( dx == 2 ) && ( dy == 1 ) )
        {
            //position: D3
            for ( j = -1; j < B4_SIZE + 2; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_QUART_LT[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
        }

        else if ( ( dx == 2 ) && ( dy == 3 ) )
        {
            //position: D4
            for ( j = -1; j < B4_SIZE + 2; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, x = -1; x < 3; x++ )
                        result += img_y_dec[ref_frame][RFM_MAX( 0, RFM_MIN( maxold_y, y_pos + j ) )][RFM_MAX( 0, RFM_MIN( maxold_x, x_pos + i + x ) )] * COEF_HALF[x + 1];

                    //tmp_res[j + 1][i] = result;
                    tmp_res[j+1][i]=RFM_MAX( 0, RFM_MIN( 255, ( result+4 ) / 8 ) );
                }
            }
            for ( j = 0; j < B4_SIZE; j++ )
            {
                for ( i = 0; i < B4_SIZE; i++ )
                {

                    for ( result = 0, y = -1; y < 3; y++ )
                        result += tmp_res[j + y + 1][i] * COEF_QUART_RB[y + 1];

                    //block[i][j] = RFM_MAX(0, RFM_MIN(255, (result) / 64));  // ???? +32
                    block[i][j]=RFM_MAX( 0, RFM_MIN( 255, ( result+2 ) / 4 ) );
                }
            }
        }
#endif
    }
}
#endif
/*
*************************************************************************
* Function:
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void get_block_uv( macroblock_t *currMB, int uv )
{
    int i, j, ref_idx, pic_y, pic_x, dir, x, y, x_offset[2], y_offset[2];
    int pred_x, pred_y;
    int mode;
    byte **ref_frm[MAX_REF_NUM];
    mv_t mv[2];
    int xh, yh;
    int tmp_pred[2][8][8];
    int blk4x4_y,blk4x4_x;

    mode = currMB->mb_type;

    for ( j = 0; j < 2; j++ )
    {
        for ( i = 0; i < 2; i++ )
        {
            pic_y  = img->pix_c_y + 4 * j;
            pic_x  = img->pix_c_x + 4 * i;
            pred_y = 4 * j;
            pred_x = 4 * i;

            if( mode == INTER8x8 && currMB->subblock_type[2*j +i] == SUBBLOCK_INTER4x4 )
            {
                for ( blk4x4_y=0; blk4x4_y<=1; blk4x4_y++ )
                {
                    for ( blk4x4_x=0; blk4x4_x<=1; blk4x4_x++ )
                    {
                        if ( currMB->b4_ref[2*j+i][2*blk4x4_y+blk4x4_x] != BI )
                        {
                            byte    refpix[4];
                            int     intpix[2];
                            if( img->type==P_IMG )
                            {
                                ref_idx   = frm_mv_4x4[MAX_REF_NUM][img->block8_y+j][img->block8_x+i][blk4x4_y][blk4x4_x].ref;//currMB->b8_ref[j][i];
                                mv[ref_idx].x   = frm_mv_4x4[MAX_REF_NUM][img->block8_y+j][img->block8_x+i][blk4x4_y][blk4x4_x].x;//img->mv[ref_idx][mode][j][i];
                                mv[ref_idx].y   = frm_mv_4x4[MAX_REF_NUM][img->block8_y+j][img->block8_x+i][blk4x4_y][blk4x4_x].y;//img->mv[ref_idx][mode][j][i];
                            }
                            else    //B frame
                            {
                                ref_idx = currMB->b4_ref[2*j+i][2*blk4x4_y+blk4x4_x];
                                if ( FW == ref_idx )
                                {
                                    mv[ref_idx].x = frm_bi_mv_4x4[img->block8_y+j][img->block8_x+i][blk4x4_y][blk4x4_x].fw_mv.x;
                                    mv[ref_idx].y = frm_bi_mv_4x4[img->block8_y+j][img->block8_x+i][blk4x4_y][blk4x4_x].fw_mv.y;
                                }
                                else   // BW
                                {
                                    mv[ref_idx].x = frm_bi_mv_4x4[img->block8_y+j][img->block8_x+i][blk4x4_y][blk4x4_x].bw_mv.x;
                                    mv[ref_idx].y = frm_bi_mv_4x4[img->block8_y+j][img->block8_x+i][blk4x4_y][blk4x4_x].bw_mv.y;
                                }
                            }

                            ref_frm[ref_idx] = img_uv_dec[uv][ref_idx];

#if QUARTER_PIXEL
							xh        = mv[ref_idx].x & 7;//hlv, 2012.9.28
							yh        = mv[ref_idx].y & 7;
							mv[ref_idx].x >>= 3;  //  UV half mv
							mv[ref_idx].y >>= 3;  //  UV half mv
#else
                            xh        = mv[ref_idx].x & 3;
                            yh        = mv[ref_idx].y & 3;
                            mv[ref_idx].x >>= 2;  //  UV half mv
                            mv[ref_idx].y >>= 2;  //  UV half mv
#endif
                            x_offset[ref_idx] = mv[ref_idx].x + pic_x + blk4x4_x*2;
                            y_offset[ref_idx] = mv[ref_idx].y + pic_y + blk4x4_y*2;

#define clipx(val) RFM_CLIP3(val,0,img->width_cr-1)
#define clipy(val) RFM_CLIP3(val,0,img->height_cr-1)

                            for ( y = 0; y < 2; y++ )
                            {
                                for ( x = 0; x < 2; x++ )
                                {
                                    refpix[0] = ref_frm[ref_idx][clipy( y_offset[ref_idx] + y  )][clipx( x_offset[ref_idx] + x  )];
                                    refpix[1] = ref_frm[ref_idx][clipy( y_offset[ref_idx] + y  )][clipx( x_offset[ref_idx] + x+1 )];
                                    refpix[2] = ref_frm[ref_idx][clipy( y_offset[ref_idx] + y+1 )][clipx( x_offset[ref_idx] + x  )];
                                    refpix[3] = ref_frm[ref_idx][clipy( y_offset[ref_idx] + y+1 )][clipx( x_offset[ref_idx] + x+1 )];

#if QUARTER_PIXEL
                                    intpix[0] = refpix[0]*( 8-xh ) + refpix[1]*xh;
                                    intpix[1] = refpix[2]*( 8-xh ) + refpix[3]*xh;
                                    img->mpr[pred_x+blk4x4_x*2+x][pred_y+blk4x4_y*2+y] = ( intpix[0]*( 8-yh ) + intpix[1]*yh + 32 )>>6;
#else
                                    intpix[0] = refpix[0]*( 4-xh ) + refpix[1]*xh;
                                    intpix[1] = refpix[2]*( 4-xh ) + refpix[3]*xh;
                                    img->mpr[pred_x+blk4x4_x*2+x][pred_y+blk4x4_y*2+y] = ( intpix[0]*( 4-yh ) + intpix[1]*yh + 8 )>>4;
#endif
                                }
                            }
                        }
                        else      //  Bi direction
                        {
                            mv[0]  = frm_bi_mv_4x4[img->block8_y+j][img->block8_x+i][blk4x4_y][blk4x4_x].fw_mv;
                            mv[1]  = frm_bi_mv_4x4[img->block8_y+j][img->block8_x+i][blk4x4_y][blk4x4_x].bw_mv;
                            for ( dir = 0; dir < BI; dir++ )
                            {
                                byte    refpix[4];
                                int     intpix[2];
                                ref_frm[dir] = img_uv_dec[uv][dir];

#if QUARTER_PIXEL
                                xh        = mv[dir].x & 7;
                                yh        = mv[dir].y & 7;
                                mv[dir].x >>= 3;  //  UV half mv
                                mv[dir].y >>= 3;  //  UV half mv
#else
                                xh        = mv[dir].x & 3;
                                yh        = mv[dir].y & 3;
                                mv[dir].x >>= 2;  //  UV half mv
                                mv[dir].y >>= 2;  //  UV half mv
#endif
                                x_offset[dir] = mv[dir].x + pic_x + blk4x4_x*2;
                                y_offset[dir] = mv[dir].y + pic_y + blk4x4_y*2;

                                for ( y = 0; y < 2; y++ )
                                {
                                    for ( x = 0; x < 2; x++ )
                                    {
                                        refpix[0] = ref_frm[dir][clipy( y_offset[dir] + y  )][clipx( x_offset[dir] + x  )];
                                        refpix[1] = ref_frm[dir][clipy( y_offset[dir] + y  )][clipx( x_offset[dir] + x+1 )];
                                        refpix[2] = ref_frm[dir][clipy( y_offset[dir] + y+1 )][clipx( x_offset[dir] + x  )];
                                        refpix[3] = ref_frm[dir][clipy( y_offset[dir] + y+1 )][clipx( x_offset[dir] + x+1 )];

#if QUARTER_PIXEL
                                        intpix[0] = refpix[0]*( 8-xh ) + refpix[1]*xh;
                                        intpix[1] = refpix[2]*( 8-xh ) + refpix[3]*xh;
                                        tmp_pred[dir][pred_y+blk4x4_y*2 +y][pred_x+ blk4x4_x*2+x] = ( intpix[0]*( 8-yh ) + intpix[1]*yh + 32 )>>6;
#else
                                        intpix[0] = refpix[0]*( 4-xh ) + refpix[1]*xh;
                                        intpix[1] = refpix[2]*( 4-xh ) + refpix[3]*xh;
                                        tmp_pred[dir][pred_y+blk4x4_y*2 +y][pred_x+ blk4x4_x*2+x] = ( intpix[0]*( 4-yh ) + intpix[1]*yh + 8 )>>4;
#endif
                                    }
                                }
                            }
                            //get bi-direction prediction
                            for ( y = 0; y < 2; y++ )
                            {
                                for ( x = 0; x < 2; x++ )
                                {
                                    img->mpr[pred_x+blk4x4_x*2+x][pred_y+blk4x4_y*2+y] = ( tmp_pred[FW][pred_y+blk4x4_y*2+y][pred_x+blk4x4_x*2+x] + tmp_pred[BW][pred_y+blk4x4_y*2+y][pred_x+blk4x4_x*2+x] + 1 ) >> 1;
                                }
                            }
                        }//end else bi direction
                    }//end blk4x4_x
                }//end blk4x4_y
            }//end if mode inter4x4

            //xy_110506 begin
            else if( mode == INTER8x8 && ( currMB->subblock_type[2*j +i] == SUBBLOCK_INTRA4x4 || currMB->subblock_type[2*j +i] == SUBBLOCK_INTRA8x8 ) )
            {
                for ( y = 0; y < 4; y++ )
                {
                    for ( x = 0; x < 4; x++ )
                    {
                        img->mpr[pred_x+x][pred_y+y] = 128;
                    }
                }

            } //xy_110506 end
            else //mode = inter16x16 || mode = inter8x8
            {
                if ( currMB->b8_ref[j][i] != BI )
                {
                    byte    refpix[4];
                    int     intpix[2];
                    if( img->type==P_IMG )
                    {
                        ref_idx       = frm_mv[MAX_REF_NUM][img->block8_y+j][img->block8_x+i].ref;//currMB->b8_ref[j][i];
                        mv[ref_idx].x = frm_mv[MAX_REF_NUM][img->block8_y+j][img->block8_x+i].x;//img->mv[ref_idx][mode][j][i];
                        mv[ref_idx].y = frm_mv[MAX_REF_NUM][img->block8_y+j][img->block8_x+i].y;//img->mv[ref_idx][mode][j][i];
                    }
                    else    //B frame
                    {
                        ref_idx = currMB->b8_ref[j][i];
                        if ( FW == ref_idx )
                        {
                            mv[ref_idx].x = frm_bi_mv[img->block8_y+j][img->block8_x+i].fw_mv.x;
                            mv[ref_idx].y = frm_bi_mv[img->block8_y+j][img->block8_x+i].fw_mv.y;
                        }
                        else   // BW
                        {
                            mv[ref_idx].x = frm_bi_mv[img->block8_y+j][img->block8_x+i].bw_mv.x;
                            mv[ref_idx].y = frm_bi_mv[img->block8_y+j][img->block8_x+i].bw_mv.y;
                        }
                    }

#if QUARTER_PIXEL
					xh        = mv[ref_idx].x & 7;
					yh        = mv[ref_idx].y & 7;
					mv[ref_idx].x >>= 3;  //  UV half mv
					mv[ref_idx].y >>= 3;  //  UV half mv
#else
                    xh        = mv[ref_idx].x & 3;
                    yh        = mv[ref_idx].y & 3;
                    mv[ref_idx].x >>= 2;  //  UV half mv
                    mv[ref_idx].y >>= 2;  //  UV half mv
#endif

                    x_offset[ref_idx] = mv[ref_idx].x + pic_x;
                    y_offset[ref_idx] = mv[ref_idx].y + pic_y;

#define clipx(val) RFM_CLIP3(val,0,img->width_cr-1)
#define clipy(val) RFM_CLIP3(val,0,img->height_cr-1)

                    for ( y = 0; y < 4; y++ )
                    {
                        for ( x = 0; x < 4; x++ )
                        {
                            refpix[0] = img_uv_dec[uv][ref_idx][clipy( y_offset[ref_idx] + y  )][clipx( x_offset[ref_idx] + x  )];
                            refpix[1] = img_uv_dec[uv][ref_idx][clipy( y_offset[ref_idx] + y  )][clipx( x_offset[ref_idx] + x+1 )];
                            refpix[2] = img_uv_dec[uv][ref_idx][clipy( y_offset[ref_idx] + y+1 )][clipx( x_offset[ref_idx] + x  )];
                            refpix[3] = img_uv_dec[uv][ref_idx][clipy( y_offset[ref_idx] + y+1 )][clipx( x_offset[ref_idx] + x+1 )];

#if QUARTER_PIXEL
                            intpix[0] = refpix[0]*( 8-xh ) + refpix[1]*xh;
                            intpix[1] = refpix[2]*( 8-xh ) + refpix[3]*xh;
                            img->mpr[pred_x+x][pred_y+y] = ( intpix[0]*( 8-yh ) + intpix[1]*yh + 32 )>>6;
#else
                            intpix[0] = refpix[0]*( 4-xh ) + refpix[1]*xh;
                            intpix[1] = refpix[2]*( 4-xh ) + refpix[3]*xh;
                            img->mpr[pred_x+x][pred_y+y] = ( intpix[0]*( 4-yh ) + intpix[1]*yh + 8 )>>4;
#endif
                        }
                    }
                }
                else      //  Bi direction
                {
                    mv[0]  = frm_bi_mv[img->block8_y+j][img->block8_x+i].fw_mv;
                    mv[1]  = frm_bi_mv[img->block8_y+j][img->block8_x+i].bw_mv;
                    for ( dir = 0; dir < BI; dir++ )
                    {
                        byte    refpix[4];
                        int     intpix[2];
                        ref_frm[dir] = img_uv_dec[uv][dir];
#if QUARTER_PIXEL
                        xh        = mv[dir].x & 7;
                        yh        = mv[dir].y & 7;
                        mv[dir].x >>= 3;  //  UV half mv
                        mv[dir].y >>= 3;  //  UV half mv
#else
                        xh        = mv[dir].x & 3;
                        yh        = mv[dir].y & 3;
                        mv[dir].x >>= 2;  //  UV half mv
                        mv[dir].y >>= 2;  //  UV half mv
#endif
                        x_offset[dir] = mv[dir].x + pic_x;
                        y_offset[dir] = mv[dir].y + pic_y;

                        for ( y = 0; y < 4; y++ )
                        {
                            for ( x = 0; x < 4; x++ )
                            {
                                refpix[0] = ref_frm[dir][clipy( y_offset[dir] + y  )][clipx( x_offset[dir] + x  )];
                                refpix[1] = ref_frm[dir][clipy( y_offset[dir] + y  )][clipx( x_offset[dir] + x+1 )];
                                refpix[2] = ref_frm[dir][clipy( y_offset[dir] + y+1 )][clipx( x_offset[dir] + x  )];
                                refpix[3] = ref_frm[dir][clipy( y_offset[dir] + y+1 )][clipx( x_offset[dir] + x+1 )];

#if QUARTER_PIXEL
                                intpix[0] = refpix[0]*( 8-xh ) + refpix[1]*xh;
                                intpix[1] = refpix[2]*( 8-xh ) + refpix[3]*xh;
                                tmp_pred[dir][pred_y+y][pred_x+x] = ( intpix[0]*( 8-yh ) + intpix[1]*yh + 32 )>>6;
#else
                                intpix[0] = refpix[0]*( 4-xh ) + refpix[1]*xh;
                                intpix[1] = refpix[2]*( 4-xh ) + refpix[3]*xh;
                                tmp_pred[dir][pred_y+y][pred_x+x] = ( intpix[0]*( 4-yh ) + intpix[1]*yh + 8 )>>4;
#endif
                            }
                        }
                    }
                    //get bi-direction prediction
                    for ( y = 0; y < 4; y++ )
                    {
                        for ( x = 0; x < 4; x++ )
                        {
                            img->mpr[pred_x+x][pred_y+y] = ( tmp_pred[FW][pred_y+y][pred_x+x] + tmp_pred[BW][pred_y+y][pred_x+x] + 1 ) >> 1;
                        }
                    }
                }
            }//end else !inter4x4
        }//end for i
    }
}


/*
*************************************************************************
* Function:Reads the content of two successive startcode from the bitstream
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

int Header()
{
    unsigned char *Buf;
    int startcodepos, length;
    static unsigned long prev_pos = 0;
    static unsigned long prev_pic = 0, curr_pic = 0;

    if ( ( Buf = ( unsigned char * )calloc( MAX_CODED_FRAME_SIZE, sizeof( char ) ) ) == NULL )
        no_mem_exit( "GetAnnexbNALU: Buf" );

    while ( 1 )
    {
        StartCodePosition = get_one_unit( ( char * )Buf, &startcodepos, &length );

        switch ( StartCodeValue = Buf[startcodepos] )
        {
            case SEQUENCE_HEADER_CODE:
                if ( input->check_BBV_flag && !img->new_seq_header_flag && pBbv )
                {
                    stat_bbv_buffer( pBbv );
                    pBbv = free_bbv_memory( pBbv );
                    img->new_seq_header_flag = 1;
                }

                sequence_header( ( char * )Buf, startcodepos, length );

                if ( input->check_BBV_flag && img->new_seq_header_flag )
                {
                    pBbv = init_bbv_memory( frame_rate_code, low_delay, bbv_buffer_size, bit_rate_upper, bit_rate_lower );
                    img->new_seq_header_flag = 0;
                }

                img->seq_header_indicate = 1;
                break;
            case EXTENSION_START_CODE:
                extension_data( ( char * )Buf, startcodepos, length );
                break;
            case USER_DATA_START_CODE:
                user_data( ( char * )Buf, startcodepos, length );
                break;
            case VIDEO_EDIT_CODE:
                video_edit_code_data( ( char * )Buf, startcodepos, length );
                break;
            case PICTURE_START_CODE:  //xy_110703
                curr_pic = prev_pos;
                bn = curr_pic - prev_pic;
                pic_header( ( char * )Buf, startcodepos, length ); //xy_110703
                calc_picture_distance( img );
                if ( !img->seq_header_indicate )
                {
                    img->B_discard_flag = 1;
                    fprintf( stdout, "    I   %3d\t\tDIDSCARD!!\n", img->tr );
                    break;
                }
                if ( input->check_BBV_flag )
                {
                    if ( !img->new_sequence_flag )
                    {
                        if ( ( 0xFFFF == img->last_pic_bbv_delay && 0xFFFF != bbv_delay ) || ( 0xFFFF != img->last_pic_bbv_delay && 0xFFFF == bbv_delay ) )
                        {
#if SYNTAX_REPORT
                            fprintf( p_sreport, "If one picture's bbv_delay is 0xFFFF, then all pictures's bbv_delay is 0xFFFF.\n" );
#endif
                            bbv_delay = 0xFFFF;
                        }
                    }

                    if ( 0xFFFF == bbv_delay )
                    {
                        pBbv->bbv_mode = 1;
                    }
                    else
                    {
                        if ( img->new_sequence_flag )
                        {
                            pBbv->bbv_delay = ( float )( bbv_delay / 90000.0 );
                        }
                        else if ( bbv_delay < pBbv->bbv_delay * 90000 * 0.95 || bbv_delay > pBbv->bbv_delay * 90000 * 1.05 )
                        {
#if SYNTAX_REPORT
                            fprintf( p_sreport, "\nThe bbv_delay of frame %d should be %.3f rather than %.3f.\n", FrameNum, pBbv->bbv_delay, bbv_delay / 90000.0 );
#endif
                        }
                    }

                    img->new_sequence_flag = 0;
                    img->last_pic_bbv_delay = bbv_delay;
                }

                break;

            case SEQUENCE_END_CODE:
                img->new_sequence_flag = 1;
                free( Buf );
                return EOS;
                break;
            default:
                if ( ( Buf[startcodepos] >= SLICE_START_CODE_MIN && Buf[startcodepos] <= SLICE_START_CODE_MAX ) && ( ( !img->seq_header_indicate ) || ( img->type == B_IMG && img->B_discard_flag == 1 && !img->no_forward_reference ) ) )
                {
                    break;
                }
                else if ( Buf[startcodepos] == SLICE_START_CODE_MIN )
                {
                    if ( ( temp_slice_buf = ( unsigned char * )calloc( MAX_CODED_FRAME_SIZE, sizeof( char ) ) ) == NULL ) // modified 08.16.2007
                        no_mem_exit( "GetAnnexbNALU: Buf" );
                    first_slice_length = length;
                    first_slice_startpos = startcodepos;
                    memcpy( temp_slice_buf, Buf, length );
                    free( Buf );
                    return SOP;
                }
                else
                {
                    printf( "Can't find start code" );
                    free( Buf );
                    return EOS;
                }
        }
    }

}

/*
*************************************************************************
* Function:Initializes the parameters for a new frame
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void init_frame( image_t *img, input_t *inp )
{
    static int first_P = TRUE;
    int i;

    img->top_bot = -1;
    last_P_no = last_P_no_frm;
    nextP_tr = nextP_tr_frm;

    if ( img->number == 0 )       // first picture
    {
        nextP_tr = prevP_tr = img->pic_distance;
    }
    else if ( img->type == I_IMG || img->type == P_IMG )
    {
        nextP_tr = img->pic_distance;

        if ( first_P )              // first P picture
        {
            first_P = FALSE;
            P_interval = nextP_tr - prevP_tr;
        }
#if REC_YUV
        if ( p_ref )
            find_snr( snr, img, p_ref );      // if ref sequence exist

        if ( pre_img_type == I_IMG ) // I picture
            fprintf( stdout, "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n", FrameNum, pre_img_tr, pre_img_qp, snr->snr_y, snr->snr_u, snr->snr_v, pre_tmp_time, 1 /*img->picture_structure*/ ? "FRM" : "FLD" );
        else if ( pre_img_type == P_IMG )   // P pictures
        {
            if ( pre_img_types == I_IMG )
                fprintf( stdout, "%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n", FrameNum, pre_img_tr, pre_img_qp, snr->snr_y, snr->snr_u, snr->snr_v, pre_tmp_time, 1 /*img->picture_structure*/ ? "FRM" : "FLD" ); //jlzheng 7.3
            else
                fprintf( stdout, "%3d(P)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s\n", FrameNum, pre_img_tr, pre_img_qp, snr->snr_y, snr->snr_u, snr->snr_v, pre_tmp_time, 1 /*img->picture_structure*/ ? "FRM" : "FLD" );
        }
#else
        if ( pre_img_type == I_IMG ) // I picture
            fprintf( stdout, "%3d(I)  %3d %5d %5d\t\t%s\n", FrameNum, pre_img_tr, pre_img_qp, pre_tmp_time, 1 /*img->picture_structure*/ ? "FRM" : "FLD" );
        else if ( pre_img_type == P_IMG )   // P pictures
        {
            if ( pre_img_types == I_IMG )
                fprintf( stdout, "%3d(I)  %3d %5d %5d\t\t%s\n", FrameNum, pre_img_tr, pre_img_qp, pre_tmp_time, 1 /*img->picture_structure*/ ? "FRM" : "FLD" ); //jlzheng 7.3
            else
                fprintf( stdout, "%3d(P)  %3d %5d %5d\t\t%s\n", FrameNum, pre_img_tr, pre_img_qp, pre_tmp_time, 1 /*img->picture_structure*/ ? "FRM" : "FLD" );
        }
#endif

        report_frame( snr, pre_tmp_time );
        write_prev_Pframe( img, p_out );    // imgY_prev, imgUV_prev -> file
    }
    // allocate memory for frame buffers
    if ( img->number == 0 )
    {
        init_global_buffers( inp, img );
    }


    for ( i = 0; i < img->max_mb_nr; i++ )
    {
        mb_data[i].slice_nr = -1;
    }

}


/*
*************************************************************************
* Function:decodes one picture
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void picture_data( image_t *img, input_t *inp )
{
    unsigned char *Buf;
    int mb_width = img->width / 16;
    int first_slice = 1;

    img->current_slice_nr = -1;
    currentbitoffset = currStream->frame_bitoffset;
    currStream->frame_bitoffset = 0;
    if ( ( Buf = ( unsigned char * )calloc( MAX_CODED_FRAME_SIZE, sizeof( char ) ) ) == NULL )
        no_mem_exit( "GetAnnexbNALU: Buf" );

    img->cod_counter = -1;

    while ( img->current_mb_nr < img->PicSizeInMbs )      // loop over macroblocks
    {
        if ( img->current_mb_nr % mb_width == 0 )
        {
            if ( img->cod_counter <= 0 )
            {
                if ( first_slice )
                {

                    slice_header( ( char * )temp_slice_buf, first_slice_startpos, first_slice_length );
                    free( temp_slice_buf );
                    img->current_slice_nr++;
                    img->cod_counter = -1;
                    first_slice = 0;
                    qcoder_init( qcoder, currStream );
                }
                /* else
                {
                if (check_start_code())
                {
                get_one_unit(Buf, &startcodepos, &length);
                slice_header(Buf, startcodepos, length);
                img->current_slice_nr++;
                img->cod_counter = -1;
                }
                }*/
            }
        }                           //decode slice header

        if ( img->current_mb_nr == 0 )
            img->current_slice_nr = 0;
        mb_data[img->current_mb_nr].slice_nr = img->current_slice_nr;

#if TRACE
        fprintf( p_trace, "\n*********** Pic: %i (I/P) MB: %i Slice: %i Type %d **********\n", img->tr, img->current_mb_nr, img->current_slice_nr, img->type );
#endif

        // Initializes the current macroblock
        start_macroblock( img, inp );
        if( qcoder_decode_inter_skip( qcoder ) )
            get_skipped_macroblock( img );
        else
            // Get the syntax elements from the streams
            read_one_macroblock( img, inp );
        if( img->is_discard_frame )
            break;

        // decode one macroblock
        decode_one_macroblock( img, inp );
        img->current_mb_nr++;
    }

    free( Buf );
    qcoder_flush( qcoder );

}



/*
*************************************************************************
* Function:Prepare field and frame buffer after frame decoding
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void frame_postprocessing( image_t *img )
{
    if ( ( img->number ) && ( img->type == I_IMG || img->type == P_IMG ) )
    {
        nextP_tr_frm = nextP_tr;
    }
    if ( img->type == I_IMG || img->type == P_IMG )
    {
        img->PrevPicDistanceLsb = img->pic_distance;
        img->PicDistanceMsb = img->CurrPicDistanceMsb;
    }
}

/*
******************************************************************************
*  Function: Determine the MVD's value (1/4 pixel) is legal or not.
*  Input:
*  Output:
*  Return:   0: out of the legal mv range; 1: in the legal mv range
*  Attention:
*  Author: Xiaozhen ZHENG, rm52k
******************************************************************************
*/
void DecideMvRange()
{
    if ( profile_id == 0x20 )
    {
        switch ( level_id )
        {
            case 0x10:
                Min_V_MV = -512;
                Max_V_MV = 511;
                Min_H_MV = -8192;
                Max_H_MV = 8191;
                break;
            case 0x20:
                if ( 1 /*img->picture_structure*/ )
                {
                    Min_V_MV = -1024;
                    Max_V_MV = 1023;
                }
                else
                {
                    Min_V_MV = -512;
                    Max_V_MV = 511;
                }
                Min_H_MV = -8192;
                Max_H_MV = 8191;
                break;
            case 0x22:
                if ( 1 /*img->picture_structure*/ )
                {
                    Min_V_MV = -1024;
                    Max_V_MV = 1023;
                }
                else
                {
                    Min_V_MV = -512;
                    Max_V_MV = 511;
                }
                Min_H_MV = -8192;
                Max_H_MV = 8191;
                break;
            case 0x40:
                if ( 1 /*img->picture_structure*/ )
                {
                    Min_V_MV = -2048;
                    Max_V_MV = 2047;
                }
                else
                {
                    Min_V_MV = -1024;
                    Max_V_MV = 1023;
                }
                Min_H_MV = -8192;
                Max_H_MV = 8191;
                break;
            case 0x42:
                if ( 1 /*img->picture_structure*/ )
                {
                    Min_V_MV = -2048;
                    Max_V_MV = 2047;
                }
                else
                {
                    Min_V_MV = -1024;
                    Max_V_MV = 1023;
                }
                Min_H_MV = -8192;
                Max_H_MV = 8191;
                break;
        }
    }
}
